<!DOCTYPE html>
<meta charset="utf-8">
<title>Slowparse Error Reporting Specification</title>
<style>
html, body {
  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-size: small;
}

body {
  width: 800px;
  margin: 0 auto 1em auto;
}

div.report > h2:before {
  content: "ERROR TYPE: ";
  color: gray;
}

.test.failed div.report > h2:before {
  content: 'FATAL ERROR';
  color: black;
}

pre, div.js {
  font-family: Menlo, Monaco, "Lucida Console", monospace;
}

div.console {
  background: black;
  padding: 10px;
}

div.js {
  color: lightgreen;
}

div.js > div {
  display: pre;
}

div.js > div:before {
  content: '> ';
  color: gray;
}

pre.result {
  color: lightgray;
}

pre.html {
  background: #f0f0f0;
  color: black;
  padding: 10px;
}

.color-1 {
  background: pink;
}

.color-2 {
  background: black;
  color: white;
}

.error em {
  font-style: inherit;
}

a {
  color: inherit;
}

.test {
  margin-top: 3em;
  border-left: 1px solid black;
  padding-left: 0.5em;
}

.test.failed, .test.failed .html {
  background: firebrick;
}

.test.failed div.console {
  background: darkred;
}

.test > div.js, .test > div.bad-html {
  display: none;
}

h1.error-category {
  border-top: 1px dotted gray;
  border-bottom: 1px dotted gray;
}
</style>
<h1>Slowparse Error Reporting Specification</h1>
<p>All of the following documentation is generated on-the-fly,
  in your browser, by <a href="../?slowparse.js">slowparse.js</a> and <a href="../?errors.jquery.js">errors.jquery.js</a>. If something looks amiss, run the actual 
  output against the expected results at the <a href="../test/">test suite</a>;
  if errors are reported, please feel free to
  <a href="https://github.com/mozilla/slowparse/issues">file a bug</a>.</p>
<p>You can also consult the <a href="../demo/">live demo</a> to see this error
  reporting used in an interactive widget.</p>
<div id="templates" style="display: none">
  <div class="report">
    <h2></h2>
    <h3>Example</h3>
    <pre class="html"></pre>
    <div class="error"></div>
    <h3>JavaScript Code</h3>
    <div class="console">
      <div class="js">
        <div>Slowparse.findError({{HTML}});</div>
      </div>
      <pre class="result"></pre>
    </div>
  </div>
</div>
<h1 class="error-category">HTML Errors</h1>
<div class="test">
  <script type="text/x-bad-html">
    hi</i>
  </script>
  <script type="application/json">
  {
    "type": "UNEXPECTED_CLOSE_TAG",
    "closeTag": {
      "name": "i",
      "start": 2,
      "end": 5
    }
  }
  </script>
</div>
<div class="test">
  <script type="text/x-bad-html">
    <p>hi</i>
  </script>
  <script type="application/json">
  {
    "type": "MISMATCHED_CLOSE_TAG",
    "openTag": {
      "name": "p",
      "start": 0,
      "end": 3
    },
    "closeTag": {
      "name": "i",
      "start": 5,
      "end": 8
    }
  }
  </script>
</div>
<div class="test">
  <script type="text/x-bad-html">
    <br>hello</br>
  </script>
  <script type="application/json">
  {
    "type": "CLOSE_TAG_FOR_VOID_ELEMENT",
    "closeTag": {
      "name": "br",
      "start": 9,
      "end": 13
    }
  }
  </script>
</div>
<div class="test">
  <script type="text/x-bad-html">
    hello<p/>there
  </script>
  <script type="application/json">
  {
    "type": "SELF_CLOSING_NON_VOID_ELEMENT",
    "name": "p",
    "start": 5,
    "end": 9
  }
  </script>
</div>
<div class="test">
  <script type="text/x-bad-html">
    hello <em>there
  </script>
  <script type="application/json">
  {
    "type": "UNCLOSED_TAG",
    "openTag": {
      "name": "em",
      "start": 6,
      "end": 10
    }
  }
  </script>
</div>
<div class="test">
  <script type="text/x-bad-html">
    <-lol>
  </script>
  <script type="application/json">
  {
    "type": "INVALID_TAG_NAME",
    "openTag": {
      "name": "",
      "start": 0,
      "end": 1
    }
  }
  </script>
</div>
<div class="test">
  <script type="text/x-bad-html">
    hello <em>there</em dude.
  </script>
  <script type="application/json">
  {
    "type": "UNTERMINATED_CLOSE_TAG",
    "closeTag": {
      "name": "em",
      "start": 15,
      "end": 19
    }
  }
  </script>
</div>
<div class="test">
  <script type="text/x-bad-html">
    <a class=foo bar>
  </script>
  <script type="application/json">
  {
    "type": "UNQUOTED_ATTR_VALUE",
    "start": 9
  }
  </script>
  <h3>Notes</h3>
  <p>The HTML5 specification actually allows unquoted attribute
    values, so long as they don't have spaces in them. However,
    this isn't commonly done outside of minifying HTML. Furthermore, by
    complicating the standard, our predictions about the user's
    intent also become ambiguous, which results in more cryptic
    and confusing error messages. By choosing to enforce monotony, we
    ease the learning process and provide more helpful
    errors.</p>
</div>
<div class="test">
  <script type="text/x-bad-html">
    hello <em </em>
  </script>
  <script type="application/json">
  {
    "type": "UNTERMINATED_OPEN_TAG",
    "openTag": {
      "start": 6,
      "end": 10,
      "name": "em"
    }
  }
  </script>
</div>
<div class="test">
  <script type="text/x-bad-html">
    hello <em class="foo>there</em>
  </script>
  <script type="application/json">
  {
    "type": "UNTERMINATED_ATTR_VALUE",
    "openTag": {
      "name": "em",
      "start": 6
    },
    "attribute": {
      "name": {
        "value": "class",
        "start": 10,
        "end": 15
      },
      "value": {
        "start": 16
      }
    }
  }
  </script>
</div>
<div class="test">
  <script type="text/x-bad-html">
    hello <em class='foo>there</em>
  </script>
  <script type="application/json">
  {
    "type": "UNTERMINATED_ATTR_VALUE",
    "openTag": {
      "name": "em",
      "start": 6
    },
    "attribute": {
      "name": {
        "value": "class",
        "start": 10,
        "end": 15
      },
      "value": {
        "start": 16
      }
    }
  }
  </script>
</div>
<div class="test">
  <script type="text/x-bad-html">
    hello <em class="foo'>there</em>
  </script>
  <script type="application/json">
  {
    "type": "UNTERMINATED_ATTR_VALUE",
    "openTag": {
      "name": "em",
      "start": 6
    },
    "attribute": {
      "name": {
        "value": "class",
        "start": 10,
        "end": 15
      },
      "value": {
        "start": 16
      }
    }
  }
  </script>
</div>
<div class="test">
  <script type="text/x-bad-html">
    hello <em class='foo">there</em>
  </script>
  <script type="application/json">
  {
    "type": "UNTERMINATED_ATTR_VALUE",
    "openTag": {
      "name": "em",
      "start": 6
    },
    "attribute": {
      "name": {
        "value": "class",
        "start": 10,
        "end": 15
      },
      "value": {
        "start": 16
      }
    }
  }
  </script>
</div>
<div class="test">
  <script type="text/x-bad-html">
    hi<!--blah
  </script>
  <script type="application/json">
  {
    "type": "UNTERMINATED_COMMENT",
    "start": 2
  }
  </script>
</div>

<h1 class="error-category">CSS Errors</h1>
<div class="test">
  <script type="text/x-bad-html">
    <style> a
  </script>
  <script type="application/json">
  {
    "type": "UNFINISHED_CSS_SELECTOR",
    "cssSelector": {
      "start": 8,
      "end": 9,
      "selector": "a"
    }
  }
  </script>
</div>
<div class="test">
  <script type="text/x-bad-html">
    <style> a {
  </script>
  <script type="application/json">
  {
    "type": "MISSING_CSS_PROPERTY",
    "cssSelector": {
      "start": 8,
      "end": 9,
      "selector": "a"
    }
  }
  </script>
</div>
<div class="test">
  <script type="text/x-bad-html">
    <style> a { color
  </script>
  <script type="application/json">
  {
    "type": "UNFINISHED_CSS_PROPERTY",
    "cssProperty": {
      "start": 12,
      "end": 17,
      "property": "color"
    }
  }
  </script>
</div>
<div class="test">
  <script type="text/x-bad-html">
    <style> a { color:
  </script>
  <script type="application/json">
  {
    "type": "MISSING_CSS_VALUE",
    "cssProperty": {
      "start": 12,
      "end": 17,
      "property": "color"
    }
  }
  </script>
</div>
<div class="test">
  <script type="text/x-bad-html">
    <style> a { colour:
  </script>
  <script type="application/json">
  {
    "type": "INVALID_CSS_PROPERTY_NAME",
    "cssProperty": {
      "start": 12,
      "end": 18,
      "property": "colour"
    }
  }
  </script>
</div>
<div class="test">
  <script type="text/x-bad-html">
    <style> a { color: red
  </script>
  <script type="application/json">
  {
    "type": "UNFINISHED_CSS_VALUE",
    "cssValue": {
      "start": 19,
      "end": 22,
      "value": "red"
    }
  }
  </script>
</div>
<div class="test">
  <script type="text/x-bad-html">
    <style> a { color: red;
  </script>
  <script type="application/json">
  {
    "type": "MISSING_CSS_BLOCK_CLOSER",
    "cssValue": {
      "start": 19,
      "end": 22,
      "value": "red"
    }
  }
  </script>
</div>
<div class="test">
  <script type="text/x-bad-html">
    <style> a { color: red; }
  </script>
  <script type="application/json">
  {
    "type": "MISSING_CSS_SELECTOR",
    "cssBlock": {
      "start": 24,
      "end": 25
    }
  }
  </script>
</div>
<div class="test">
  <script type="text/x-bad-html">
    <style> a { li {
  </script>
  <script type="application/json">
  {
    "type": "MISSING_CSS_BLOCK_CLOSER",
    "cssValue": {
      "start": 8,
      "end": 12,
      "value": "a"
    }
  }
  </script>
</div>

<div class="test">
  <div class="bad-html">
    &lt;style&gt;
      &lt;!-- html comment in CSS block --&gt;
    &lt;/style&gt;
  </div>
  <script type="application/json">
  {
    "type": "HTML_CODE_IN_CSS_BLOCK",
    "html": {
      "start": 13,
      "end": 14
    }
  }
    </script>
</div>
<div class="test">
  <script type="text/x-bad-html">
    <style>
      <p>html code in CSS block</p>
    </style>
  </script>
  <script type="application/json">
  {
    "type": "HTML_CODE_IN_CSS_BLOCK",
    "html": {
      "start": 13,
      "end": 14
    }
  }
  </script>
</div>

<div class="test">
  <script type="text/x-bad-html">
    <style> /* unterminated comment
  </script>
  <script type="application/json">
  {
    "type": "UNTERMINATED_CSS_COMMENT",
    "start": 8
  }
  </script>
</div>

<h1 class="error-category">FORBIDJS Errors</h1>
<p>The <code>tree-inspectors.js</code> script must be included to enable these errors.</p>
<div class="test">
  <div class="bad-html">
    hi&lt;script&gt;alert('yo');&lt;/script&gt;
  </div>
  <div class="js">Slowparse.findError({{HTML}}, [TreeInspectors.forbidJS]);</div>
  <script type="application/json">
  {
    "type": "SCRIPT_ELEMENT_NOT_ALLOWED",
    "openTag": {
      "start": 2,
      "end": 10
    },
    "closeTag": {
      "start": 22,
      "end": 31
    }
  }
  </script>
</div>
<div class="test">
  <script type="text/x-bad-html">
    <p onclick="alert('yo');">hi</p>
  </script>
  <div class="js">Slowparse.findError({{HTML}}, [TreeInspectors.forbidJS]);</div>
  <script type="application/json">
  {
    "type": "EVENT_HANDLER_ATTR_NOT_ALLOWED",
    "name": {
      "start": 3,
      "end": 10
    },
    "value": {
      "start": 11,
      "end": 25
    }
  }
  </script>
</div>
<div class="test">
  <script type="text/x-bad-html">
    <a href="javascript:alert('yo');">hi</a>
  </script>
  <div class="js">Slowparse.findError({{HTML}}, [TreeInspectors.forbidJS]);</div>
  <script type="application/json">
  {
    "type": "JAVASCRIPT_URL_NOT_ALLOWED",
    "name": {
      "start": 3,
      "end": 7
    },
    "value": {
      "start": 8,
      "end": 33
    }
  }
  </script>
</div>


<script src="../vendor/jquery.min.js"></script>
<script src="../slowparse.js"></script>
<script src="../tree-inspectors.js"></script>
<script src="spec.js"></script>
<script src="errors.jquery.js"></script>
